﻿// original from sf under GNU LESSER GENERAL PUBLIC LICENSE 
// http://sourceforge.net/projects/rc4dotnet
// simplified by me  and fixed for files
using System;
using System.IO;
using System.Text;


public class RC4 : ICoder
{
    private const int EncodingCode = 1251;

    public void Encrypt(string password, string file, string targetFile)
    {
        byte[] content = encrypt(password, File.ReadAllBytes(file));
        File.WriteAllBytes(targetFile, content);
    }

    public void Decrypt(string password, string file, string targetFile)
    {
        byte[] content = encrypt(password, File.ReadAllBytes(file));
        File.WriteAllBytes(targetFile, content);
    }

    private int getAsciiCode(char character)
    {
        return (int)(Encoding.GetEncoding(EncodingCode).GetBytes(character + "")[0]);
    }

    private char fromAsciiCode(int asciiCode)
    {
        byte[] bytes = new byte[1];
        bytes[0] = (byte)asciiCode;
        return Encoding.GetEncoding(EncodingCode).GetString(bytes)[0];
    }

    private string hexToBinary(string packtype, string datastring)
    {
        int i, j, datalength, packsize;
        byte[] bytes;
        char[] hex;
        string tmp;

        datalength = datastring.Length;
        packsize = (datalength / 2) + (datalength % 2);
        bytes = new byte[packsize];
        hex = new char[2];

        for (i = j = 0; i < datalength; i += 2)
        {
            hex[0] = datastring[i];
            if (datalength - i == 1)
                hex[1] = '0';
            else
                hex[1] = datastring[i + 1];
            tmp = new string(hex, 0, 2);
            try { bytes[j++] = byte.Parse(tmp, System.Globalization.NumberStyles.HexNumber); }
            catch { } /* grin */
        }
        return Encoding.GetEncoding(EncodingCode).GetString(bytes);
    }

    public string binaryToHex(string bindata)
    {
        int i;
        byte[] bytes = Encoding.GetEncoding(EncodingCode).GetBytes(bindata);
        string hexString = "";
        for (i = 0; i < bytes.Length; i++)
        {
            hexString += bytes[i].ToString("x2");
        }
        return hexString;
    }

    private byte[] encrypt(string password, byte[] data)
    {
        int a, i, j, k, tmp, pwd_length, data_length;
        int[] key, box;
        byte[] cipheredText;

        password = hexToBinary("H*", password); // valid input, please!
        pwd_length = password.Length;
        data_length = data.Length;
        key = new int[256];
        box = new int[256];
        cipheredText = new byte[data.Length];

        for (i = 0; i < 256; i++)
        {
            key[i] = getAsciiCode(password[i % pwd_length]);
            box[i] = i;
        }
        for (j = i = 0; i < 256; i++)
        {
            j = (j + box[i] + key[i]) % 256;
            tmp = box[i];
            box[i] = box[j];
            box[j] = tmp;
        }
        for (a = j = i = 0; i < data_length; i++)
        {
            a = (a + 1) % 256;
            j = (j + box[a]) % 256;
            tmp = box[a];
            box[a] = box[j];
            box[j] = tmp;
            k = box[((box[a] + box[j]) % 256)];
            cipheredText[i] = (byte)(data[i] ^ k);
        }
        return cipheredText;
    }

}